package org.ofbiz.steel.generate;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

//import org.ofbiz.autoconfig.auto.AutoUtils;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.ServiceUtil;
import org.ofbiz.base.util.Debug;

import com.alibaba.fastjson.JSONObject;

import javolution.util.FastList;
import javolution.util.FastMap;

public class FreeMakerServices {

	public static final String module = FreeMakerServices.class.getName(); 
	public static final String OFBIZ_HOME = System.getProperty("ofbiz.home");

	@SuppressWarnings("unchecked")
	public static Map<String, Object> codeGenerate(DispatchContext ctx, Map<String, ? extends Object> context) {
		Delegator delegator = ctx.getDelegator();
		Map<String, Object> result = ServiceUtil.returnSuccess();
		String code = (String) context.get("code");
		String projectPath = (String) context.get("projectPath");
		String jspMode = (String) context.get("jspMode");
		String ftlDescription = (String) context.get("ftlDescription");
		String jformType = (String) context.get("jformType");
		String tableName_tmp = (String) context.get("tableName_tmp");
		String entityName = (String) context.get("entityName");
		String entityPackage = (String) context.get("entityPackage");
		String packageStyle = (String) context.get("packageStyle");
		String tableName = (String) context.get("tableName");
		List<String> nfsList = FastList.newInstance();
		String codeTypes = "service,entity,vue";
		try {
			String fileInName = OFBIZ_HOME + "/applications/steel/config/code-template-auto";

			String fileOutName = OFBIZ_HOME + "/runtime/tmp/autocode";
			GenericValue entity = delegator.findOne("OnlScFormHead", UtilMisc.toMap("id", code), false);
			List<GenericValue> fieldList = delegator.findByAnd("OnlScFormField", UtilMisc.toMap("cgformHeadId", code),
					UtilMisc.toList("orderNum"), false);
			String tableType = entity.getString("tableType");
			String isTree = entity.getString("isTree");
			String fileTmp = "";
			String fileTmpStr = "";
			if (tableType.equals("1")) { 
				if (isTree.equals("N")) {
					fileTmp = fileInName + "/default/one";
					fileTmpStr = "1";
				} else {
					fileTmp = fileInName + "/default/tree";
					fileTmpStr = "2";
				}
			} else if (tableType.equals("2")) {
				if (jspMode.equals("many")) {
					fileTmp = fileInName + "/default/onetomany";
					fileTmpStr = "3";
				} else if (jspMode.equals("erp")) {
					fileTmp = fileInName + "/erp/onetomany";
					fileTmpStr = "4";
				} else if (jspMode.equals("innerTable")) {
					fileTmp = fileInName + "/inner-table/onetomany";
					fileTmpStr = "5";
				}
			}

			String[] codeTypeList = codeTypes.split(",");
 
			Map<String, Object> map = new HashMap<String, Object>();
			List<Map<String, Object>> columns = FastList.newInstance();
			for (GenericValue field : fieldList) {
				Map<String, Object> columnMap = FastMap.newInstance();
				if (UtilValidate.isNotEmpty(field.getString("dictTable"))) {
					String dictTable = field.getString("dictTable");
					if (dictTable.contains("condition")) {
						Map<String, Object> dictMap = dictToMapFree(dictTable);
						columnMap.put("dictTable", dictMap.get("table"));
						columnMap.put("dictText", dictMap.get("txt"));
						columnMap.put("dictField", dictMap.get("key"));
						String dictCondition = dictMap.get("condition").toString();
						columnMap.put("dictCondition", dictCondition);
						columnMap.put("oldDictTable", field.getString("dictTable"));
						
						columnMap.put("dictTableCap", String.valueOf(dictMap.get("table")));
						columnMap.put("dictTextCap", String.valueOf(dictMap.get("txt")));
						columnMap.put("dictFieldCap", String.valueOf(dictMap.get("key")));

						// 组装查询数据
					} else {
						columnMap.put("dictTable", field.getString("dictTable"));
						columnMap.put("dictText", field.getString("dictText"));
						columnMap.put("dictField", field.getString("dictField"));
						columnMap.put("dictCondition", "");

						columnMap.put("dictTableCap", String.valueOf(field.get("dictTable")));
						columnMap.put("dictTextCap", String.valueOf(field.get("dictText")));
						columnMap.put("dictFieldCap", String.valueOf(field.get("dictField")));
					}
				}

				columnMap.put("filedComment", field.getString("dbFieldTxt"));
				columnMap.put("fieldShowType", field.getString("fieldShowType"));
				columnMap.put("classType", field.getString("fieldShowType"));

				columnMap.put("fieldValidType", field.getString("fieldValidType"));
				columnMap.put("fieldName", field.getString("dbFieldName"));
				columnMap.put("fieldDbName", field.getString("dbFieldName"));
				columnMap.put("fieldDbType", field.getString("dbType"));
				columnMap.put("fieldDbIsKey", field.getString("dbIsKey"));
				columnMap.put("queryMode", field.getString("queryMode"));

				if (field.getString("fieldMustInput").equals("0")) {
					columnMap.put("nullable", "Y");
				} else {
					columnMap.put("nullable", "N");
				}

				if (field.getLong("isQuery") == 0) {
					columnMap.put("isQuery", "N");
				} else {
					columnMap.put("isQuery", "Y");
				}
				if (field.getLong("isShowForm") == 0) {
					columnMap.put("isShow", "N");
				} else {
					columnMap.put("isShow", "Y");
				}
				if (field.getLong("isShowList") == 0) {
					columnMap.put("isShowList", "N");
				} else {
					columnMap.put("isShowList", "Y");
				}
				columns.add(columnMap);
			}

			Map<String, Object> tableVo = FastMap.newInstance();
			tableVo.put("ftlDescription", ftlDescription);
			tableVo.put("tableName", tableName);

			Map<String, Object> extendParams = FastMap.newInstance();
			extendParams.put("scroll", entity.getString("autoScroll"));
			extendParams.put("hasChildren", entity.getString("treeIdField"));
			extendParams.put("pidField", entity.getString("treeParentIdField"));
			extendParams.put("textField", entity.getString("treeFieldname"));

			tableVo.put("extendParams", extendParams);

			map.put("originalColumns", columns);
			map.put("columns", columns);
			String formTemplateMobile = entity.getString("formTemplateMobile");
			if (UtilValidate.isEmpty(formTemplateMobile)) {formTemplateMobile = "12";}
			map.put("formTemplateMobile", formTemplateMobile);
			map.put("entityName", entityName);
			map.put("tableVo", tableVo);
			map.put("entityPackage", entityPackage);
			map.put("tableName_tmp", tableName_tmp);
			map.put("tableName", tableName);
			map.put("importName", tableName.replace("_", "-"));
			map.put("tableType", fileTmpStr);

//	    map.put("hasChildrenField", entity.getString("treeIdField"));
//	    map.put("pidFieldName", entity.getString("treeParentIdField"));

			// 字表
			List<Map<String, Object>> subTables = FastList.newInstance();
			if (tableType.equals("2")) {
				List<String> subTableList = splitCustomStringToList(entity.getString("subTableStr"), ",");
				for (String subTable : subTableList) {
					List<GenericValue> list = delegator.findByAnd("OnlScFormHead",
							UtilMisc.toMap("copyType", 0L, "tableName", subTable, "tableType", 3L), null, false);
					GenericValue subTab = EntityUtil.getFirst(list);

					List<GenericValue> subFieldList = delegator.findByAnd("OnlScFormField",
							UtilMisc.toMap("cgformHeadId", subTab.getString("id")), UtilMisc.toList("orderNum"), false);

					Map<String, Object> subMap = FastMap.newInstance();

					subMap.put("foreignRelationType", subTab.getString("relationType"));
					subMap.put("ftlDescription", subTab.getString("tableTxt"));
					subMap.put("entityName", subTab.getString("tableName"));
					subMap.put("subEntityName", subTab.getString("tableName"));
					subMap.put("tableName", subTab.getString("tableName"));
					subMap.put("importName", subTab.getString("tableName").replace("_", "-"));

					List<Map<String, Object>> subColums = FastList.newInstance();
					List<String> foreignKeys = FastList.newInstance();
					List<Map<String, String>> foreignKeyList = FastList.newInstance();
					for (GenericValue field : subFieldList) {
						Map<String, Object> columnMap = FastMap.newInstance();
						if (UtilValidate.isNotEmpty(field.getString("dictTable"))) {
							String dictTable = field.getString("dictTable");
							if (dictTable.contains("condition")) {
								Map<String, Object> dictMap = dictToMapFree(dictTable);
								columnMap.put("dictTable", dictMap.get("table"));
								columnMap.put("dictText", dictMap.get("txt"));
								columnMap.put("dictField", dictMap.get("key"));
								String dictCondition = dictMap.get("condition").toString();
								columnMap.put("dictCondition", dictCondition);
								columnMap.put("oldDictTable", field.getString("dictTable"));

								columnMap.put("dictTableCap", String.valueOf(dictMap.get("table")));
								columnMap.put("dictTextCap", String.valueOf(dictMap.get("txt")));
								columnMap.put("dictFieldCap", String.valueOf(dictMap.get("key")));

								// 组装查询数据
								/**
								 * 当前的控件 j-multi-select-tag j-search-select-tag j-dict-select-tag j-popup
								 * 
								 * 
								 */
							} else {
								columnMap.put("dictTable", field.getString("dictTable"));
								columnMap.put("dictText", field.getString("dictText"));
								columnMap.put("dictField", field.getString("dictField"));
								columnMap.put("dictCondition", "");

								columnMap.put("dictTableCap", String.valueOf(field.get("dictTable")));
								columnMap.put("dictTextCap", String.valueOf(field.get("dictText")));
								columnMap.put("dictFieldCap", String.valueOf(field.get("dictField")));
							}
						}
						columnMap.put("filedComment", field.getString("dbFieldTxt"));
						columnMap.put("fieldName", field.getString("dbFieldName"));
						columnMap.put("fieldShowType", field.getString("fieldShowType"));
						columnMap.put("classType", field.getString("fieldShowType"));

						columnMap.put("fieldValidType", field.getString("fieldValidType"));
						if (field.getString("fieldMustInput").equals("0")) {
							columnMap.put("nullable", "Y");
						} else {
							columnMap.put("nullable", "N");
						}

						if (field.getLong("isQuery") == 0) {
							columnMap.put("isQuery", "N");
						} else {
							columnMap.put("isQuery", "Y");
						}
						if (field.getLong("isShowForm") == 0) {
							columnMap.put("isShow", "N");
						} else {
							columnMap.put("isShow", "Y");
						}
						if (field.getLong("isShowList") == 0) {
							columnMap.put("isShowList", "N");
						} else {
							columnMap.put("isShowList", "Y");
						}
						if (UtilValidate.isNotEmpty(field.get("mainTable"))) {
							foreignKeys.add(field.getString("dbFieldName"));
							if (tableName.equals(field.get("mainTable"))) {
								foreignKeyList.add(UtilMisc.toMap("filedName", field.getString("dbFieldName"),
										"fieldValue", field.getString("mainField")));
							}
						}

						columnMap.put("fieldDbName", field.getString("dbFieldName"));
						columnMap.put("fieldDbType", field.getString("dbType"));
						columnMap.put("fieldDbIsKey",field.getString("dbIsKey"));
						columnMap.put("queryMode", field.getString("queryMode"));
						subColums.add(columnMap);
					}
					subMap.put("foreignKeyList", foreignKeyList);
					subMap.put("originalColumns", subColums);
					subMap.put("colums", subColums);
					subMap.put("foreignKeys", foreignKeys); // 外键列表

					subTables.add(subMap);
				}

				map.put("subTables", subTables);
			}

			String newFileTmp = fileTmp + "/java";

			for (String codeType : codeTypeList) {
				if (codeType.equals("vue")) {
					String codeFileTmp = newFileTmp + "/vue";
					if (fileTmpStr.equals("1")) {
						String fileTmp1 = codeFileTmp + "/${entityName}List.vuei";
						String fileTmp2 = codeFileTmp + "/modules/${entityName}Modal.vuei";
						String fileTmp3 = codeFileTmp + "/modules/${entityName}Modal__Style#Drawer.vuei";

						String fileOutTmp1 = fileOutName + "/" + entityPackage + "/vue/" + entityName + "List.vue";
						readTemplateToWriteFile(fileTmp1, map, fileOutTmp1);

						String fileOutTmp2 = fileOutName + "/" + entityPackage + "/vue/modules/" + entityName
								+ "Modal.vue";
						readTemplateToWriteFile(fileTmp2, map, fileOutTmp2);

						String fileOutTmp3 = fileOutName + "/" + entityPackage + "/vue/modules/" + entityName
								+ "Modal__Style#Drawer.vue";
						readTemplateToWriteFile(fileTmp3, map, fileOutTmp3);

						nfsList.add("生成成功 : " + fileOutTmp1);
						nfsList.add("生成成功 : " + fileOutTmp2);
						nfsList.add("生成成功 : " + fileOutTmp3);
					} else if (fileTmpStr.equals("2")) {
						String fileTmp1 = codeFileTmp + "/${entityName}List.vuei";
						String fileTmp2 = codeFileTmp + "/modules/${entityName}Modal.vuei";

						String fileOutTmp1 = fileOutName + "/" + entityPackage + "/vue/" + entityName + "List.vue";
						readTemplateToWriteFile(fileTmp1, map, fileOutTmp1);

						String fileOutTmp2 = fileOutName + "/" + entityPackage + "/vue/modules/" + entityName
								+ "Modal.vue";
						readTemplateToWriteFile(fileTmp2, map, fileOutTmp2);

						nfsList.add("生成成功 : " + fileOutTmp1);
						nfsList.add("生成成功 : " + fileOutTmp2);
					} else if (fileTmpStr.equals("3")) {
						String fileTmp1 = codeFileTmp + "/${entityName}List.vuei";
						String fileTmp2 = codeFileTmp + "/modules/${entityName}Modal.vuei";
						String fileOutTmp1 = fileOutName + "/" + entityPackage + "/vue/" + entityName + "List.vue";
						readTemplateToWriteFile(fileTmp1, map, fileOutTmp1);

						String fileOutTmp2 = fileOutName + "/" + entityPackage + "/vue/modules/" + entityName
								+ "Modal.vue";
						readTemplateToWriteFile(fileTmp2, map, fileOutTmp2);
						nfsList.add("生成成功 : " + fileOutTmp1);
						nfsList.add("生成成功 : " + fileOutTmp2);

						String fileTmp3 = codeFileTmp + "/modules/[1-n]Form.vuei";
						String fileOutTmp3 = fileOutName + "/" + entityPackage + "/vue/modules/1-nForm.vue";
						readTemplateToWriteFile(fileTmp3, map, fileOutTmp3);

						for (int i = 0; i < subTables.size(); i++) {
							Map<String, Object> sub = subTables.get(i);
							nfsList.add("生成成功 : " + fileOutName + "/" + entityPackage + "/vue/modules/"
									+ sub.get("entityName") + "Form.vue");
						}

					} else if (fileTmpStr.equals("4")) {
						String fileTmp1 = codeFileTmp + "/${entityName}List.vuei";
						String fileTmp3 = codeFileTmp + "/modules/${entityName}Modal.vuei";

						String fileOutTmp1 = fileOutName + "/" + entityPackage + "/vue/" + entityName + "List.vue";
						readTemplateToWriteFile(fileTmp1, map, fileOutTmp1);

						String fileOutTmp3 = fileOutName + "/" + entityPackage + "/vue/modules/" + entityName
								+ "Modal.vue";
						readTemplateToWriteFile(fileTmp3, map, fileOutTmp3);

						nfsList.add("生成成功 : " + fileOutTmp1);
						nfsList.add("生成成功 : " + fileOutTmp3);

						String fileTmp2 = codeFileTmp + "/[1-n]List.vuei";
						String fileOutTmp2 = fileOutName + "/" + entityPackage + "/vue/" + "1-nList.vue";
						readTemplateToWriteFile(fileTmp2, map, fileOutTmp2);
						for (int i = 0; i < subTables.size(); i++) {
							Map<String, Object> sub = subTables.get(i);
							nfsList.add("生成成功 : " + fileOutName + "/" + entityPackage + "/vue/" + sub.get("entityName")
									+ "List.vue");
						}

						String fileTmp4 = codeFileTmp + "/modules/[1-n]Modal.vuei";
						String fileOutTmp4 = fileOutName + "/" + entityPackage + "/vue/modules/" + "1-nModal.vue";
						readTemplateToWriteFile(fileTmp4, map, fileOutTmp4);
						for (int i = 0; i < subTables.size(); i++) {
							Map<String, Object> sub = subTables.get(i);
							nfsList.add("生成成功 : " + fileOutName + "/" + entityPackage + "/vue/modules/"
									+ sub.get("entityName") + "Modal.vue");
						}

					} else if (fileTmpStr.equals("5")) {
						String fileTmp1 = codeFileTmp + "/${entityName}List.vuei";
						String fileTmp3 = codeFileTmp + "/modules/${entityName}Modal.vuei";

						String fileOutTmp1 = fileOutName + "/" + entityPackage + "/vue/" + entityName + "List.vue";
						readTemplateToWriteFile(fileTmp1, map, fileOutTmp1);

						String fileOutTmp3 = fileOutName + "/" + entityPackage + "/vue/modules/" + entityName
								+ "Modal.vue";
						readTemplateToWriteFile(fileTmp3, map, fileOutTmp3);

						nfsList.add("生成成功 : " + fileOutTmp1);
						nfsList.add("生成成功 : " + fileOutTmp3);

						String fileTmp2 = codeFileTmp + "/subTables/[1-n]SubTable.vuei";
						String fileOutTmp2 = fileOutName + "/" + entityPackage + "/vue/subTables/" + "1-nSubTable.vue";
						readTemplateToWriteFile(fileTmp2, map, fileOutTmp2);
						for (int i = 0; i < subTables.size(); i++) {
							Map<String, Object> sub = subTables.get(i);
							nfsList.add("生成成功 : " + fileOutName + "/" + entityPackage + "/vue/subTables/"
									+ sub.get("entityName") + "SubTable.vue");
						}

						String fileTmp4 = codeFileTmp + "/modules/[1-n]Form.vuei";
						String fileOutTmp4 = fileOutName + "/" + entityPackage + "/vue/modules/" + "1-nForm.vue";
						readTemplateToWriteFile(fileTmp4, map, fileOutTmp4);
						for (int i = 0; i < subTables.size(); i++) {
							Map<String, Object> sub = subTables.get(i);
							nfsList.add("生成成功 : " + fileOutName + "/" + entityPackage + "/vue/modules/"
									+ sub.get("entityName") + "Form.vue");
						}

					}
				} else if (codeType.equals("service")) {
					String codeFileTmp = newFileTmp + "/service";
					String fileTmp1 = codeFileTmp + "/services.xmli";
					String fileTmp2 = codeFileTmp + "/${entityName}Services.xmli";

					String fileOutTmp1 = fileOutName + "/" + entityPackage + "/service/services.xml";
					readTemplateToWriteFile(fileTmp1, map, fileOutTmp1);

					String fileOutTmp2 = fileOutName + "/" + entityPackage + "/service/" + entityName + "Services.xml";
					readTemplateToWriteFile(fileTmp2, map, fileOutTmp2);

					nfsList.add("生成成功 : " + fileOutTmp1);
					nfsList.add("生成成功 : " + fileOutTmp2);
				}
			}
			result.put("nfsList", nfsList);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (GenericEntityException e) {
			e.printStackTrace();
		}
		return result;
	}

	private static void readTemplateToWriteFile(String templateUrl, Map<String, Object> dataMap, String outFileUrl)
			throws IOException {
		Debug.log("templateUrl = "+templateUrl);
		Debug.log("dataMap = "+dataMap);
		String result = FreemarkerTemplateUtils.processTemplate(templateUrl, dataMap);
		Debug.log("result = "+result);
		if (result.contains("#segment#")) {
			String[] s = result.split("#segment#");
			for (int i = 0; i < s.length; i++) {
				if (UtilValidate.isNotEmpty(s[i])) {
					String ftlStr = s[i];
					int indexOfLength = 0;
					String indexOfStr = "";
					if (outFileUrl.contains("1-nForm.vue")) {
						indexOfLength = 8;
						indexOfStr = "Form.vue";
					} else if (outFileUrl.contains("1-nList.vue")) {
						indexOfLength = 8;
						indexOfStr = "List.vue";
					} else if (outFileUrl.contains("1-nModal.vue")) {
						indexOfLength = 9;
						indexOfStr = "Modal.vue";
					} else if (outFileUrl.contains("1-nSubTable.vue")) {
						indexOfLength = 12;
						indexOfStr = "SubTable.vue";
					}
					String fileName = ftlStr.substring(0, ftlStr.indexOf(indexOfStr) + indexOfLength);
					String viewText = ftlStr.substring(ftlStr.indexOf(indexOfStr) + indexOfLength, ftlStr.length());
					if (UtilValidate.isNotEmpty(fileName)) {
						String newUrl = outFileUrl.substring(0, outFileUrl.lastIndexOf("/")) + "/" + fileName;
						writeString(newUrl, viewText);
					}
				}
			}
		} else {
			writeString(outFileUrl, result);
		}
	}

	private static void writeString(String fileName, String s) throws IOException {
		String path = fileName.substring(0, fileName.lastIndexOf("/"));
		fileName = fileName.substring(fileName.lastIndexOf("/") + 1, fileName.length());
		SteelFileUtil.writeString(path, fileName, s);
	}
	
	private static Map<String, Object> dictToMapFree(String dictTable) {
		Map<String, Object> resultMap = new HashMap<>();
		JSONObject jasonObject = JSONObject.parseObject(dictTable);
		resultMap = (Map<String, Object>) jasonObject;
		Iterator<Map.Entry<String, Object>> it = resultMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, Object> entry = it.next();
			String key = entry.getKey();
			String pkValue = (String) entry.getValue();
			resultMap.put(key, pkValue);
		}
		return resultMap;
	}
	
	private static List splitCustomStringToList(String inputString, String splitChar) {
		List result = FastList.newInstance();
		if (UtilValidate.isEmpty(inputString)) {
			return result;
		}
		inputString = inputString.trim(); 
		String[] array = inputString.split(splitChar);
		for (int i = 0; i < array.length; i++) {
			if (UtilValidate.isNotEmpty(array[i])) {
				result.add(array[i]);
			}
		}
		return result;
	}
}